＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝

                        PC-FXGAオーサリングソフトウェア
                 『ＧＭＡＫＥＲ』スタータキットプラス(Ver.1.0)
                            ”ＳＣＤＥＶ．Ａ”の解説

                                        日本電気ホームエレクトロニクス株式会社
                                                            １９９６年４月８日

＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝

目次

第１章　SCSIライブラリ概要
１．１	SCSIライブラリのセグメント
１．２	使用法

第２章　SCSIライブラリ関数
２．１　SCSIインターフェースのイニシャライズ                     init_scsi
２．２　SCSIバスをリセットする                                   reset_scsi
２．３　ターゲットシステムにコマンドを送出する                   scsi
２．４  scsi、read28のためのDMA終了割り込みハンドラ              scsi_dma_int
２．５  scsi、read28のためのフェーズミスマッチ割り込みハンドラ   scsi_block_int
２．６　read28のためにCD-ROMと接続する                           open_read28
２．７　CD-ROMからデータを転送する                               read28
２．８　read28を終了する                                         close_read28
２．９　メモリ領域を 0 でクリアする                              bzero

＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝
第１章　SCSIライブラリ概要

SCSIライブラリはターゲットシステムにコマンドを送り、データの転送を行なう
低レベルの通信手順を受け持ちます。
またDMA転送もサポートしているので、バックグラウンドでデータの受取りができます。
HuC6271とHuC6230を使った画像と音声データの連続再生に使うことも可能です。


■１．１  SCSIライブラリのセグメント

SCSIライブラリは以下のセグメントに配置されます。

属性            セグメント名称
コード部        scsi_code
データ部        scsi_data
ＢＳＳ部        scsi_bss
ゼロページ部    無し


■１．２　使用法

必要な関数を呼び、リンク時にscdev.aをリンクして下さい。

《例》

fxlk /cseg+scsi_code+dseg+scsi_data+bseg+scsi_bss src1.o src2.o scdev.a

＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝
第２章　SCSIライブラリ関数

■２．１　SCSIインターフェースのイニシャライズ

《名　称》
init_scsi

《形　式》
#include <scsi.h>

void init_scsi(void);


《アセンブラ形式》
include "scsi.sh"

call    init_scsi

《解　説》
HuC6272のSCSIインターフェースをイニシャライズし、SCSIバスをリセットします。
また、SCSIライブラリのワークをイニシャライズし、SCSIライブラリを使用可能にしま
す。
scsi、read28を使用するに先だって呼んで下さい。
HuC6272の割り込みを許可する前に実行して下さい。

《関連事項》
int scsi(SCSI *scsi_cmd);
void reset_scsi(void);
int read28(unsigned long rbuf, int read_len);


■２．２　SCSIバスをリセットする

《名　称》
reset_scsi

《形　式》
#include <scsi.h>

void reset_scsi(void);

《アセンブラ形式》
include "scsi.sh"

call    reset_scsi

《解　説》
SCSIバスにリセット信号を出力します。

《関連事項》
int scsi(SCSI *scsi_cmd);
void init_scsi(void);
int read28(unsigned long rbuf, int read_len);


■２．３　ターゲットシステムにコマンドを送出する

《名　称》
scsi

《形　式》
#include <scsi.h>

int scsi(SCSI *scsi_cmd);

《アセンブラ形式》
include "scsi.sh"

mov.w   #AddressOfStructSCSI,ra0
call    scsi

《解　説》
scsiはコマンドをターゲットシステムに送出して、データのやりとりをします。
SCSI構造体にパラメータをセットしてscsiを呼び出します。

read28 や リードモード READ_KRAM_DMA で読み込み中の場合や、セレクションに失敗し
た場合は -1 を返します。正常にコマンドを送出できた場合は 0 を返します。

scsiでは構造体SCSIを次のように定義しています。

struct scsi_cmd {
　unsigned int istat;           /* initiator status */
　unsigned int tstat;           /* target status */
　unsigned int unit;            /* target unit no */
　unsigned int mess;            /* message */
　unsigned char *data;          /* address of data buffer */
　unsigned int count;           /* data count */
　unsigned int block;           /* block size */
　unsigned int mode;            /* read mode */
　unsigned char *cmd;           /* command data block */
};
typedef struct scsi_cmd SCSI;

<istat>
イニシエータのステータスが返ります。

bit7:INIT_OK
コマンドが終了したことを示します。このビット以外が立っている時は、ターゲットと
の間になんらかの異常があったことを示します。  

bit6:INIT_TO
セレクションフェーズで、ターゲットからの反応がなく、タイムアウトしたことを示し
ます。最低限の待ち時間しか用意されていませんので、使う側でリトライが必要な場合
があります。

bit5:INIT_DL
実際の転送量とcountで指定したサイズがあっていないことを示します。

bit4:INIT_BUSY
現在modeがREAD_KRAM_DMAで読んでいる最中か、read28を使用中であることを示します。

bit3:INIT_DMA
READ_KRAM_DMAで読んでいる最中に、ＳＣＳＩバスのフェーズが変わってしまいDMA読み
込みを中断したことを示します。

#define INIT_OK 0x80            /* good */
#define INIT_TO 0x40            /* time out */
#define INIT_DL 0x20            /* bad data length */
#define INIT_BUSY 0x10          /* scsi controller busy */
#define INIT_DMA 0x08           /* DMA aborted */

<tstat>
ターゲットのステータスが返ります。
詳細はSCSI及び「ＳＣＳＩコマンドの解説」のマニュアルを参照して下さい。

#define TRGT_BUSY       0x8
#define TRGT_CM         0x4
#define TRGT_CC         0x2
#define TRGT_GOOD       0x0

<unit>
ターゲットのIDビットを指定します。通常はIDが２ですので0x04を指定します。

<mess>
ターゲットからのメッセージが返ります。
scsiでは、Command Completeメッセージのみが返ります。

<data>
データの転送元のアドレスまたは転送先のアドレスを指定します。modeがREAD_MRAMの場
合はメインメモリのアドレスを、modeがREAD_KRAMかREAD_KRAM_DMAの場合はHuC6272のSC
SI DMA スタートアドレスレジスタ（REG.9）に与える値を指定します。

<count>
データの転送バイト数を指定します。modeがREAD_MRAMの場合は転送バイト数を、READ_K
RAMかREAD_KRAM_DMAの場合はHuC6272のSCSI KRAM DMAのバイトカウンタレジスタ(REG.A)
に与える値を指定します。
システムの制限上、偶数バイト指定して下さい。

<mode>
リ−ド時のデータの転送モ−ドを指定します。
　　READ_MRAM　　　　MRAM に転送します。
　　　　　 　　　　　転送が終了するまで復帰しません。
　　READ_KRAM　　　　KRAM に転送します。
　　　　　 　　　　　転送が終了するまで復帰しません。
　　READ_KRAM_DMA　　KRAM に転送します。
　　　　　 　　　　　転送はプログラムと非同期に行なわれ、すぐに復帰します。
　　　　 　　　　　　終了するとistatにINIT_OKが立ちます。
　　　　　　　　　 　割り込みハンドラでscsi_dma_int及びscsi_block_intを
　　　　 　　　 　 　呼び出して下さい。

・READ_KRAM と READ_KRAM_DMAの違いについて

　READ_KRAM と READ_KRAM_DMA はどちらも SCSI から KRAM への DMA を用いて転送を
  行いますが、２つの違いは、ユ−ザ−プログラムへ復帰するタイミングのみです。

　READ_KRAM は、SCSI のステ−タスフェ−ズ、メッセ−ジフェーズの処理が終わり、
　バスフリ−フェーズになったらユ−ザ−プログラムへ復帰します。

　READ_KRAM_DMA は、SCSI バスがデ−タインフェ−ズになって SCSI DMA を起動した
  直後にユ−ザ−プログラムへ復帰します。（DMA 終了時の処理、転送終了時のフェー
  ズの変移の処理を行う為に、ユ−ザ−プログラム側の HuC6272 の割り込みハンドラ
  で scsi_dma_int 及び scsi_block_int を呼び出す必要があります。）

<cmd>  
CDB（Command Descriptor Block）へのポインタを指定します。
CDBの詳細はSCSI及び「ＳＣＳＩコマンドの解説」のマニュアルを参照して下さい。

《注意》
システムの制限上、ノンアービトレーションシステムです。また、ターゲット機能はあ
りません。

Disconnect/Reconnectはサポートしていません。

コマンドのリンク機能はサポートしていません。リンクビットは常に０にして下さい。

拡張メッセージはサポートしていません。ターゲットから受けとるメッセージはCommand
 Completeのみです。

データインはMRAM、KRAM共できますが、データアウトはMRAMからのみです。

エラー処理はアプリケーション側で実行して下さい。check conditionなどが出た時はア
プリケーション側でrequest senseを実行して下さい。

SCSIに関してはJISX6051やISO9316などの規格書やSCSIの解説書を参照して下さい。
ベンダユニークコマンドに関しては、「SCSIコマンドの解説」のマニュアルを参照して
下さい。

この関数を呼び出すに当たって、scsi_dma_int及びscsi_block_intを割り込みハンドラ
に設定して下さい。

《関連事項》
void init_scsi(void);
void reset_scsi(void);
int scsi_dma_int(void);
int scsi_block_int(void);

《プログラム例》
#include <scsi.h>

SCSI sccmd;
unsigned char cdb[12];

main()
{
SCSI *scc;

/* TEST UNIT コマンドを発行する */
scc = &sccmd;
bzero(scc, sizeof(SCSI));
bzero(cdb, sizeof(cdb));
scc->unit = CD_ID;
scc->cmd = cdb;
scsi(scc);
}

■２．４  scsi、read28のためのDMA終了割り込みハンドラ

《名　称》
scsi_dma_int

《形　式》
#include <scsi.h>

int scsi_dma_int(void);

《アセンブラ形式》
include "scsi.sh"

call    scsi_dma_int

《解　説》
scsiでリードモードにREAD_KRAM_DMAを指定した時、または、read28を使用した時の割り
込み付きDMA転送の後処理を実行します。これ以外の原因の時は、割り込みをクリアする
だけです。割り込みハンドラでHuC6272の割り込みステータスのSCDMA.I(bit13)がオンの
時、呼び出して下さい。

scsiのREAD_KRAM_DMAでデータを読み込んだ時はDMA_SCSIが返ります。
read28で読み込んだ時はDMA_READ28が返ります。その他の原因の時はDMA_OTHER(-1)が返
ります。

《関連事項》
int scsi(SCSI *scsi_cmd);
int read28(unsigned long rbuf, int read_len);

《プログラム例》
#include <system.h>
#include <v93.h>
#include <scsi.h>

/* 割り込みハンドラ */
void king_intjob(){
if (__INPORTH(IO_KING_SRL) & 0x2000){
/* KING の割り込みステータスのSCDMA.I(bit13)がオンの時*/

int stat;

stat = scsi_dma_int();
switch (stat) {
case DMA_SCSI:    /* scsi() の READ_KRAM_DMAINT で読み込んだ時 */
:
:
break;
case DMA_READ28:  /* read28() で読み込んだ時    */
:
:
break;
case DMA_OTHER:   /* その他の原因の時    */
:
:
break;
default:
:
:
break;
}
}
}


■２．５  scsi、read28のためのフェーズミスマッチ割り込みハンドラ

《名　称》
scsi_block_int


《形　式》
#include <scsi.h>

int scsi_block_int(void);


《アセンブラ形式》
include "scsi.sh"

call    scsi_block_int

《解　説》
scsiでリードモードにREAD_KRAM_INTを指定した時、またはread28を使用した時のフェー
ズミスマッチ割り込みの後処理を実行します。これ以外の原因の時は割り込みをクリア
するだけです。
割り込みハンドラでHuC6272の割り込みステータスのSCSIBK.I(bit14)がオンの時、呼び
出して下さい。

この割り込みハンドラはDMAを使ったデータ読み込み時、なんらかのトラブルがCD-ROMで
発生した時にSCSIバスのフェーズの変わりめを検知し、ハングアップを防止します。

scsiのREAD_KRAM_DMAでデータを読み込んでいる時はPMM_DMA_SCSIが返ります。read28で
読み込んでいる時はPMM_DMA_READ28が返ります。
その他の原因の時はPMM_OTHER(-1)が返ります。

《関連事項》
int scsi(SCSI *scsi_cmd);
int read28(unsigned long rbuf, int read_len);


■２．６　read28のためにCD-ROMと接続する

《名　称》
open_read28  

《形　式》
#include <scsi.h>

int open_read28(READ28 *rprm);

《アセンブラ形式》
include "scsi.sh"

mov.w   #AddressOfStructREAD28,ra0
call    open_read28

《解　説》
open_read28はrprmの内容にしたがってCD-ROMと接続します。

open_read28は構造体READ28を次のように定義しています。

struct read28_prm {
    int stat;                /* function status */
    unsigned int id_bit;     /* target unit id bit */
    long block;              /* start block */
    int blklen;              /* block length */
    int scsi_stat;           /* scsi status phase value */
};
typedef struct read28_prm READ28;

<stat>
ステータスが返ります。
ステータスは次のように定義されています。

READ28_END          読み込みがすべて終わった。
READ28_IDLE         読み込み指示待ちである。
READ28_READ         読み込み中である。
READ28_BUSY         SCSIコントローラが使われている。
                    すでにopen_read28が呼び出されているか、scsiがREAD_KRAM_INT
                    で読みだし中である。
READ28_NOT_CONNECT  セレクションできなかった。
READ28_BREAK        なんらかのエラーが起きて中断した。
READ28_ABORT        アボートメッセージを出力して中断した。

<id_bit>
ターゲットのIDを指定します。

<block>
開始ブロックを指定します。

<blklen>
ブロック数を指定します。

<scsi_stat>
ターゲットのステータスが設定されます。

open_read28が成功すると０が返ります。失敗すると−１が返り、rprm->statに原因が設
定されます。

《注　意》
READ EXTENDコマンドを使用しているのでブロック数の最大は0xffffです。

この関数を呼び出すに当たって、scsi_dma_int及びscsi_block_intを割り込みハンドラ
に設定して下さい。

《関連事項》
int read28(unsigned long rbuf, int read_len);
int close_read28(void);
int scsi_dma_int(void);
int scsi_block_int(void);


■２．７　CD-ROMからデータを転送する

《名　称》
read28

《形　式》
#include <scsi.h>

int read28(unsigned long rbuf,int read_len);

《アセンブラ形式》
include "scsi.sh"

mov.w   #ReadBuf,ra0
mov.w   #ReadLen,ra1
call    read28

《解　説》
read28はCD-ROMからread_lenで指定したバイト数のデータをrbufで指定されるKRAMバッ
ファへ読み込みます。この関数は１回の接続で大量のデータを細切れで読み出すために
使います。この関数を呼び出すに先だって割り込みハンドラにscsi_dma_int及びscsi_bl
ock_intを設定して下さい。

呼び出しが成功するとDMAコントローラに指示した転送バイト数が返ります。返ってきた
値が０である場合は、読み込みが最後まで達してしまっていることを示します。呼び出
しが失敗すると−１が返ります。

この関数からリターンしてきてもデータの読み出しが終了しているとは限りません。
バッファのデータが有効になるとopen_read28で指定したrprm->statにREAD28_IDLEまた
はREAD28_ENDがセットされます。読みだし中はREAD28_READがセットされます。READ28_I
DLEとREAD28_ENDの違いはREAD28_ENDにセットされていると読み出せるデータがもうない
ことを示します。

読み込み中に、CD-ROMに読み込みエラー等のトラブルが起きた時は、rprm->statにREAD2
8_BREAKが設定され、read28は打ち切られます。
この時rprm->scsi_statにTRGT_CCが設定されていた時はrequest senseして、エラーの原
因を調べて下さい。

《注　意》
read_lenはバイト単位で指定できますがハードウェアの制限上２バイト単位になりま
す。端数は切り上げられます。

この関数を呼び出すに当たって、scsi_dma_int及びscsi_block_intを割り込みハンドラ
に設定して下さい。

《関連事項》
void init_scsi(void);
int open_read28(READ28 *rprm);
int close_read28(void);
int scsi_dma_int(void);
int scsi_block_int(void);

《プログラム例》
#include <system.h>
#include <scsi.h>

READ28 re;

main()
{
  init_scsi();

  re.id_bit = CD_ID;  /* ID 2( 0b0000_0100) */
  re.block = 0xaac5;  /* 転送開始ブロック */
  re.blklen = 256;    /* 総転送ブロック数 */
  if(open_read28(&re)){ /* ターゲットと接続 */
    /* エラー処理 */
             :
             :
  }else{
    for(i = 0;i < 32;i++){
      if(break_f) break;
      read28((i & 1)?0x10000:0,0x4000); /* １６ＫＢ転送指示 */
      while(re.stat == READ28_READ);
      if(re.stat == READ28_BREAK){
        if(re.scsi_stat == TRGT_CC){
           /* エラー処理 */
        }
        break;
      }
      /* 連続再生表示処理など... */
    }
    close_read28();
  }
}          


■２．８　read28を終了する

《名　称》
close_read28

《形　式》
#include <scsi.h>

int close_read28(void);

《アセンブラ形式》
include "scsi.sh"

call    close_read28

《解　説》
close_read28はread28を終了します。
読み込みが最後まで終わっていない時は、アテンション状態にして、ABORTメッセージを
ターゲットに送り強制的にコマンドを終了させます。

open_read28していない時は−１が返ります。成功した時は０が返ります。ABORTメッセ
ージを送った時はREAD28 *rprm->statにREAD28_ABORTを設定します。

《注　意》
この関数を呼び出すに当たって、scsi_dma_int及びscsi_block_intを割り込みハンドラ
に設定して下さい。

《関連事項》
int read28(unsigned long rbuf, int read_len);
int open_read28(READ28 *rprm);


■２．９　メモリ領域を 0 でクリアする

《名　称》
bzero

《形　式》
#include <scsi.h>

void bzero(void *buf,int len);

《アセンブラ形式》
include "scsi.sh"

mov.w   #Buf,ra0
mov.w   #Len,ra1
call    bzero

《解　説》
bzeroはメモリ領域をデータ 0 でクリアします。

buf にはクリアしたいメモリ領域の先頭を指定します。len にはクリアする長さをバイ
ト数で指定します。

構造体 SCSI を初期化する場合や、コマンドデータブロックを初期化する場合に使用し
て下さい。

《プログラム例》
#include <scsi.h>

SCSI sccmd;
unsigned char cdb[12];

main()
{
SCSI *scc;

/* TEST UNIT コマンドを発行する */
scc = &sccmd;
bzero(scc, sizeof(SCSI));
bzero(cdb, sizeof(cdb));
scc->unit = CD_ID;
scc->cmd = cdb;
scsi(scc);
}

＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝

《著作権及び登録商標等》

・SCDEV.A 及び SCDEV.TXT（以下、"本ソフトウェア"という）は、ＰＣ−ＦＸＧＡ用の
  ソフトウェア開発ツールの一部です。
  本ソフトウェアを、ＰＣ−ＦＸ、ＰＣ−ＦＸＧＡ用のソフトウェア開発以外の目的で
  使用しないで下さい。

・本ソフトウェアを使用した結果、直接及び間接的に生じた損害について、株式会社ハ
  ドソンは、一切の責任または債務を負わないものとします。

・本ソフトウェアの操作方法、技術的内容、その他の質問について、株式会社ハドソン
  では、直接お答えしていません。お問い合わせはご遠慮下さい。

・本ソフトウェアの使用に際し、「ソフトウェアのご使用条件」をよくご覧いただき、
  ご利用下さいますようお願い致します。

・本ソフトウェアの著作権は、株式会社ハドソンが保有しています。


MS-DOSは米国マイクロソフト社の登録商標です。
その他、記載されている会社名、製品名は、各社の登録商標または商標です。


                                                            (C)1996 HUDSON SOFT
